package com.heihei;

import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.DeploymentBuilder;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class HolidayRequest {

    public static void main(String[] args) {
        //创建  ProcessEngineConfiguration  相关配置
        ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
                .setJdbcUrl("jdbc:h2:mem:flowable;DB_CLOSE_DELAY=-1")
                .setJdbcUsername("sa")
                .setJdbcPassword("")
                .setJdbcDriver("org.h2.Driver")
                .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        //根据相关配置，创建  processEngine  对象
        ProcessEngine processEngine = cfg.buildProcessEngine();

        /**
         要将流程定义部署到Flowable引擎，使用了RepositoryService，可以从ProcessEngine对象中检索。使用RepositoryService，通过传递XML
         文件的位置并调用deploy（）方法来实际执行它，创建一个新的部署：
         */
        //根据 processEngine 创建  repositoryService
        //repositoryService可以执行发布操作，将流程定义发布到  Flowable引擎
        RepositoryService repositoryService = processEngine.getRepositoryService();
        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("holiday-request.bpmn20.xml")
                .deploy();

        /**
         现在，我们可以通过API查询流程定义来确认流程定义是否已经被引擎所了解（并学习了一些API）。这是通过RepositoryService创建一个新
         的ProcessDefinitionQuery对象来完成的。
         */
        // repositoryService  查询，可以查询出来流程定义信息  processDefinition
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deployment.getId())
                .singleResult();
        System.out.println("Found process definition : " + processDefinition.getName());


        /**
         要启动流程实例，我们需要提供一些初始流程变量。通常情况下，当某个进程被自动触发时，您将通过呈现给用户的表单或通过REST API
         获取这些表单。在这个例子中，我们将保持简单并使用java.util.Scanner类在命令行上简单地输入一些数据：
         */
        //获取请假流程的申请信息：  姓名、请假时间、请假原因详情等
        Scanner scanner= new Scanner(System.in);
//        System.out.println("Who are you?");
//        String employee = scanner.nextLine();
//        System.out.println("How many holidays do you want to request?");
//        Integer nrOfHolidays = Integer.valueOf(scanner.nextLine());
//        System.out.println("Why do you need them?");
//        String description = scanner.nextLine();

        String employee = "zhangsan";
        Integer nrOfHolidays = 3;
        String description = "tired";


        // 根据processEngine获取  runtimeService，runtimeService可以启动流程  （启动流程时，传入 员工名称、请假天数、请假原因 三个参数）
        RuntimeService runtimeService = processEngine.getRuntimeService();
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("employee", employee);
        variables.put("nrOfHolidays", nrOfHolidays);
        variables.put("description", description);
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holidayRequest", variables);

        /** 为了得到实际的任务列表，我们通过TaskService创建一个TaskQuery，并且配置查询只返回管理员组的任务： */
        //processEngine获取taskService，  taskService 可以搜索特定的任务     在此，只搜索需要 managers 处理的任务
        TaskService taskService = processEngine.getTaskService();
        List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("managers").list();
        System.out.println("You have " + tasks.size() + " tasks:");
        for (int i=0; i<tasks.size(); i++) {
            //在屏幕上打印当前任务信息
            System.out.println((i+1) + ") " + tasks.get(i).getName());
        }

        //选定要处理的流程，处理该流程
        System.out.println("Which task would you like to complete?");
        int taskIndex = Integer.valueOf(scanner.nextLine());
        Task task = tasks.get(taskIndex - 1);
        Map<String, Object> processVariables = taskService.getVariables(task.getId());
        System.out.println(processVariables.get("employee") + " wants " +
                processVariables.get("nrOfHolidays") + " of holidays. Do you approve this?");

        //输入y则表示处理
        boolean approved = scanner.nextLine().toLowerCase().equals("y");
        variables = new HashMap<String, Object>();
        variables.put("approved", approved);
        taskService.complete(task.getId(), variables);

        /** 使用历史数据 */
        HistoryService historyService = processEngine.getHistoryService();
        List<HistoricActivityInstance> activities =
                historyService.createHistoricActivityInstanceQuery()
                        .processInstanceId(processInstance.getId())
                        .finished()
                        .orderByHistoricActivityInstanceEndTime().asc()
                        .list();
        for (HistoricActivityInstance activity : activities) {
            System.out.println(activity.getActivityId() + " took "
                    + activity.getDurationInMillis() + " milliseconds");
        }
    }
}
